package grinch.edu.probtheory;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

public class LeastSquaresGraph extends View{
	
	static final int STATE_10 =   10;
	static final int STATE_100 =  100;
	static final int STATE_1000 = 1000;
	
	private int plotState;
	private int plotMethod;
	private double methodExpected;
	private double methodDispersion;
	
	private double[] randVals;
	private double[] practVals;
	
	private double koefB1;
	private double koefB0;
	
	private int coorColor  = Color.YELLOW;
	private int errorColor = Color.RED;
	private int theorColor = Color.LTGRAY;
	private int practColor = Color.MAGENTA;
	
	private int oX = 20;
	private int oY = 437;
	private int border = 20;
	private int absXpx = 1200;
	private int absYpx = 417;
	
	private int absXInterval = 20;
	private int absYInterval = 20;
	
	public LeastSquaresGraph(Context context) {
        super(context);
        setPlotState(LeastSquaresGraph.STATE_10);
        setPlotMethod(RandomExtra.METHOD_NORMAL);
        setMethodExpected(0);
        setMethodDispersion(5);
    }  
	
	public double getRandomVal(int pos){
		if ((pos >= 0)&&(pos<plotState)) return randVals[pos];
									else return 0;
	}
	
	public int getPlotState(){
		return plotState;
	}
	    
    public void setMethodExpected(double expected){
    	methodExpected = expected;
    }
    
    public void setMethodDispersion(double dispersion){
    	methodDispersion = dispersion;
    }
    
    public void setPlotMethod(int method){
    	plotMethod = method;
    }
    
    public void setPlotState(int state){
    	plotState = state;
    }
    
    public void updateValues(){
    	RandomExtra rnd = new RandomExtra();
	    randVals  = new double[plotState];
	    practVals = new double[plotState];
	    
	    for (int i=0;i<plotState;i++){
	    	randVals[i] = rnd.getRandom(plotMethod, methodExpected, methodDispersion);
	    	practVals[i] = i + randVals[i];
	    }
    }
    
    private void methodMNK (){
		double x_ = 0;
		double y_ = 0;
		double x2_ = 0;
		double xy_ = 0;
	for (int i=0;i<plotState;i++){
            x_ = x_ + i;
            x2_ = x2_ + i*i;
            y_ = y_ + practVals[i];
            xy_ = xy_ + i*practVals[i];
    }
    koefB1 = (plotState*xy_ - x_*y_)/(plotState*x2_-x_*x_);
    koefB0 = (y_/plotState - koefB1/plotState*x_);
	}
    
	@Override
	protected void onDraw(Canvas c){
	    super.onDraw(c);
	    
	    Paint paint = new Paint();
	    paint.setStyle(Paint.Style.FILL);
	    paint.setColor(coorColor);
	    
	    
	    c.drawLine(oX, oY, oX+absXpx, oY, paint);        //coorX
	    for (int i=0;i<=absXInterval;i++){
	    	int cX = oX + i*absXpx/absXInterval;
	    	c.drawLine(cX, oY+5, cX, oY-5, paint);
	    	c.drawText(String.valueOf(i), cX, oY+20, paint);
	    }
	    
	    c.drawLine(oX, border, oX, border+oY, paint);    //coorY
	    for (int i=0;i<=absYInterval;i++){
	    	int cY = oY - i*absYpx/absYInterval;
	    	c.drawLine(oX-5, cY, oX+5, cY, paint);
	    	c.drawText(String.valueOf(i), oX-20, cY, paint);
	    }
	    
	    /*
	     * Grid
	     */
	    paint.setColor(Color.rgb(44, 44, 44));
	    for (int i=1;i<=absXInterval;i++){
	    	int cX = oX + i*absXpx/absXInterval;
	    	c.drawLine(cX, oY-5, cX, border, paint);
	    }
	    for (int i=1;i<=absYInterval;i++){
	    	int cY = oY - i*absYpx/absYInterval;
	    	c.drawLine(oX+5, cY, border+absXpx, cY, paint);
	    }
	    
	    updateValues();    
	    
	    paint.setColor(errorColor);
	    for (int i=0;i<plotState;i++){
	    	int cX = oX+i*absXpx/absXInterval;
	    	int cY = (int) (oY-practVals[i]*absYpx/absYInterval);
	    	c.drawCircle(cX, cY, 3, paint);
	    }
	    methodMNK();
	    
	    
	    paint.setColor(theorColor);
	    int startX = oX;
	    int startY = oY;
	    int stopX = oX+absXpx*(plotState-1)/absXInterval;
	    int stopY = oY-absYpx*(plotState-1)/absYInterval;
	    c.drawLine(startX, startY, stopX, stopY, paint);
	    
	    
	    paint.setColor(practColor);
	    startX = oX;
	    startY = (int) (oY-koefB0*absYpx/absYInterval);
	    stopX = (int) (oX+absXpx*(plotState-1)/absXInterval);
	    stopY = (int) (oY-koefB0*absYpx/absYInterval-koefB1*absYpx*(plotState-1)/absYInterval);
	    c.drawLine(startX, startY, stopX, stopY, paint);	    
	    
	    /*
	     * History
	     */ 
	    
	    paint.setColor(theorColor);
	    c.drawLine(50, 30, 70, 30, paint);
	    c.drawText(getContext().getString(R.string.historyTheor), 80, 30, paint);
	    c.drawText("y = 1*x + 0", 80, 55, paint);
	    paint.setColor(practColor);
	    c.drawLine(160, 30, 180, 30, paint);
	    c.drawText(getContext().getString(R.string.historyPract), 190, 30, paint);
	    c.drawText("y = "+String.format("%.2f", koefB1)+"*x + "+String.format("%.2f", koefB0), 190, 55, paint);
	    paint.setColor(errorColor);
	    c.drawCircle(280, 30, 3, paint);
	    c.drawText(getContext().getString(R.string.historyError), 290, 30, paint);

	}
}